1994-1996 by Oberon microsystems, Inc., Switzerland.
All rights reserved. No part of this publication may be reproduced in any form or by any means, without prior written permission by Oberon microsystems. The only exception is the free electronic distribution of the education version of Oberon/F (see the accompanying
copyright
notice
for details).
Oberon/F module interfaces and their descriptions in particular may not be used in other works without written permission.
Oberon microsystems, Inc.
Technoparkstrasse 1
CH-8005 Z
Switzerland
Oberon is a trademark of ETH Z
rich, Switzerland.
Oberon/F, Oberon/L, "Oberon by Example", "The Oberon Tribune", "Oberon Developer Forum", and "Drag & Pick" are trademarks of Oberon microsystems, Inc.
All other trademarks and registered trademarks belong to their respective owners.
Helvetica
Helvetica
DevCommanders.StdViewDesc
DevCommanders.ViewDesc
Oberon/F
How to Develop new Components
Copyright Notice
This text gives an overview of the typical way in which new Oberon/F components are developed. It summarizes the most important aspects of what has been detailed in the user's guide.
In a first step, a subsystem name for the project is chosen, and a suitable directory created (with its Code, Docu, Mod, Rsrc, and Sym directories). This directory must be in the Oberon directory itself, i.e. at the same location where the System, Host, etc. directories are. Note that there are no environment variables or path name lists in Oberon/F. File lookup is static and determined by module names, not by configurable search paths or similar constructs. It can be convenient to provide a subsystem for private software, like test modules or personal tool commands, e.g. a subsystem Priv. The name Priv is reserved for this purpose, so there won't be conflicts with distribution software.
It is helpful to set up a text document which contains the names of all the subsystem's modules, starting with the one lowest in the module hierarchy. Such a tool text can be used as input to the Dev->Open
Module
List command. This command opens the source file of the module whose name is selected. This is convenient since it can almost eliminate the need to navigate through the directory hierarchy. As a mnemonic aid, the keyboard equivalent for Dev->Open
Module
List is the digit "0", while the keyboard equivalent of the File->Open... command is the letter "O". Dev->Open
Module
List even allows to open several files at the same time, if the selection includes several module names.
Mac OS:
If you have preferred fonts or rulers for programming, you may want to set up a stationery pad. For that purpose, create a document which is set up accordingly and save it as stationery.
Now you are ready to create the module sources, which should be placed in your subsystem's Mod directory. In order to take advantage of autoindentation, you should use tab characters for indentation. You can directly compile the module on which you are working with the Dev->Compile command. This command compiles, but does not yet load, the module. The command Dev->Compile
Module
List takes a list of module names and compiles them all.
In order to load the module, you can execute one of its exported parameterless procedures, either by executing the Dev->Execute menu command on the command's name (e.g. on Dialog.Beep), or you can augment your tool text with commanders, e.g.
Dialog.Beep (execute Tools->Insert
Commander). Once loaded, a module remains loaded, unless you explicitly unload it. Unloading can be done by executing Unload when the source code is focused, or by selecting a module name and calling Dev->Unload
Module
List. This command also works on a sequence of module names, similar to Dev->Compile
Module
List. Note that modules must be unloaded from top to bottom, since only modules which are not imported anymore may be unloaded. To check whether a module is still imported, you may call Info->Loaded
Modules. This command opens a text which lists all loaded modules. Top-level modules, i.e. modules which are not imported by other modules, have a clients count of 0. For the unloading of top-level modules, there is a shortcut if you use a commander: modifier-click on the commander first unloads the old version of the module, then loads the new version, and then calls the procedure.
In order to get quick access to a module's definition or documentation, you can use the commands Info->Interface, or Info->Documentation, respectively. Info->Interface calls the browser to construct a definition text out of a module's symbol file. Note that in this text you can select further module names (or names of imported constants, variables, types, or procedures) and get the interface of those by calling the same command again. If there is a documentation file available for a module, you can execute Info->Documentation after selecting the module's name. This command opens the documentation text. If you have selected not only the module name (e.g. Views) but an object of this module (e.g. Views.Broadcast), the command tries to find the first occurence of the object's name which is written in boldface. The name is selected, and the window scrolls to the selection's position. In the rare cases where this first occurence is not the one you need, you may call Text->Find
Again to search the next occurence.
In order to test a module, you can use module Out to write debugging output into the Log window. In order to set breakpoints, you can introduce HALT statements and recompile the module. The trap text which is opened when the HALT is reached gives you information about the call chain (stack) as it has been at the moment the command was interrupted. Note that at no point in time the normal Oberon/F environment is left; debugging takes place completely inside Oberon/F.
It is recommended to check preconditions and important invariants systematically in all programs, using the ASSERT statement. This debugging strategy is called static debugging, since error conditions are specified statically (even though they can be checked only at run-time). In an object-oriented environment, where the control flow tends to become too convoluted to follow step-by-step, the systematic application of assertions proves to keep debugging times shorter than any interactive debugging ever could.
Besides code, Oberon/F programs may also include resources. In the resource directory of a subsystem, there may be files for dialog layouts and for string mappings. Furthermore, there is a global menu configuration text. The latter can be opened with command Info->Menus, edited, and then made the current configuration by calling Info->Update
Menus.
A menu item may not only have an action command, but also a guard command. Guards mainly determine whether a menu item is currently enabled or disabled. If a guard cannot be executed (e.g. because its module cannot be loaded), the item is disabled. It is never attempted again to execute the guard command, unless explicitly requested by calling Dev->Flush
Resources. The same command also flushes an internal cache of string mappings, i.e. it should also be called after a Strings resource file has been changed.
Controls in a dialog are linked to global program variables. A new dialog is created by typing in the variable's name in the Dev->New
Form... dialog. The new dialog has a default layout, which can be modified interactively. Then the dialog should be stored in the subsystem's Rsrc directory. The properties of a control can be inspected and modified using the Edit->Object
Properties... (Windows) / Edit->Component
Info (Mac OS) command.
For some typical types of components, source code templates can be generated automatically, using the Tools->Create
Subsystem "wizard".
Distribution of an Oberon/F component simply consists of distributing its code file or subsystem directory. Installation simply consists of copying a code file or subsystem directory into the Oberon directory. If it is desired to link one or several subsystems together with an Oberon/F core, a linker can be used (not available in the education version of Oberon/F).